package net.ufrog.common.xls;

import net.ufrog.common.exception.ServiceException;
import net.ufrog.common.xls.annotation.Cell;
import net.ufrog.common.xls.annotation.Sheet;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 解析器
 * 
 * @author ultrafrog
 * @version 1.0, 2014-12-08
 * @since 1.0
 */
public class Parser {

    private static Map<Class<?>, Parser> parsers = new HashMap<>();

    /** 请求类型 */
    private Class<?> requiredType;

    /** 标签页名称 */
    private String sheetName;

    /** 标签页索引 */
    private Integer sheetIndex;

    /** 标签页标题行数 */
    private Integer sheetLabels;

    /** 字段映射 */
    private Map<Field, Cell> mCell;

    /**
     * 构造函数
     *
     * @param requiredType 请求类型
     */
    private Parser(Class<?> requiredType) {
        this.requiredType = requiredType;
        this.mCell = new HashMap<>();
        this.parse();
    }

    /**
     * 读取标签页名称
     *
     * @return 标签页名称
     * @see #sheetName
     */
    public String getSheetName() {
        return sheetName;
    }

    /**
     * 读取标签页索引
     *
     * @return 标签页索引
     * @see #sheetIndex
     */
    public Integer getSheetIndex() {
        return sheetIndex;
    }

    /**
     * 读取标签页标题行数
     *
     * @return 标签页标题行数
     * @see #sheetLabels
     */
    public Integer getSheetLabels() {
        return sheetLabels;
    }

    /**
     * 读取字段映射
     *
     * @return 字段映射
     * @see #mCell
     */
    public Map<Field, Cell> getCells() {
        return mCell;
    }

    /** 解析 */
    private void parse() {
        parseSheet();
        parseFields();
    }

    /** 解析标签 */
    private void parseSheet() {
        Sheet sheet = requiredType.getAnnotation(Sheet.class);
        if (sheet == null) throw new ServiceException("the object '" + this.requiredType.getName() + "' is not a sheet object.");
        sheetName = sheet.value();
        sheetIndex = sheet.index();
        sheetLabels = sheet.labels();
    }

    /** 解析字段 */
    private void parseFields() {
        Stream.of(requiredType.getDeclaredFields()).forEach(field -> {
            Cell cell = field.getAnnotation(Cell.class);
            if (cell != null) mCell.put(field, cell);
        });
    }

    /**
     * 获取解析器
     *
     * @param requiredType 请求类型
     * @return 解析器
     */
    public static Parser get(Class<?> requiredType) {
        if (!parsers.containsKey(requiredType)) {
            parsers.put(requiredType, new Parser(requiredType));
        }
        return parsers.get(requiredType);
    }
}
